#include "nasm/instruction/ADD.h"

namespace dspnasm {
    std::shared_ptr<ADD> ADD::genAdd(const std::string &funcUnit,
                                     const std::vector<std::shared_ptr<Operand>> &ops, bool p) {
        if (funcUnit == ".L1" || funcUnit == ".L2") {
            auto dst = Generator::computeDst(ops[2]);
            auto src2 = Generator::computeSrc2(ops[1]);
            auto src1 = Generator::computeSrc1(ops[0]);
            auto s = Generator::computeS(funcUnit);
            auto x = Generator::computeX(ops[1], s);
            std::bitset<7> op;
            if (std::dynamic_pointer_cast<SingleRegOp>(ops[0]) && std::dynamic_pointer_cast<SingleRegOp>(ops[1])) {
                op = 0b0000011;
            }
            return genAddL(0, dst, src2, src1, x, op, s, p);
        }
        return nullptr;
    }

    std::shared_ptr<ADD>
    ADD::genAddL(const std::bitset<4> &creg_z, const std::bitset<5> &dst, const std::bitset<5> &src2,
                 const std::bitset<5> &src1, const std::bitset<1> &x, const std::bitset<7> &op, const std::bitset<1> &s,
                 const std::bitset<1> &p) {
        std::shared_ptr<ADD> add = std::make_shared<ADD>();
        add->bitset[2] = false;
        add->bitset[3] = true;
        add->bitset[4] = true;
        for (u32 i = 0; i < 32; ++i) {
            if (i == 0) {
                add->bitset[i] = p[0];
            }
            if (i == 1) {
                add->bitset[i] = s[0];
            }
            if (i >= 5 && i <= 11) {
                add->bitset[i] = op[i - 5];
            }
            if (i == 12) {
                add->bitset[i] = x[0];
            }
            if (i >= 13 && i <= 17) {
                add->bitset[i] = src1[i - 13];
            }
            if (i >= 18 && i <= 22) {
                add->bitset[i] = src2[i - 18];
            }
            if (i >= 23 && i <= 27) {
                add->bitset[i] = dst[i - 23];
            }
        }
        return add;
    }
}